package dummy.perf;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import dummy.lib.NativeObject;
import dummy.test.FilterMethodTest;
import dummy.test.FilterNetworkTest;
import dummy.test.SanitizeHTMLTest;
import dummy.test.SecureClassTest;
import dummy.test.TimerTest;
import dummy.test.UserInputTest;
import dummy.test.XSSFilterTest;
import dummy.test.auth.LoginStatusFilterTest;
import dummy.test.boundry.User;
import dummy.test.boundry.UserRegistry;

public class PerformanceTest {
	
	private static final String OUTPUT_DIRECTORY = "perfnone";
	
	private static final String LOAD_CLASSES_FILE = "load_classes.txt";
	private static final String CREATE_USERS_FILE = "create_users.txt";
	private static final String NATIVE_OBJECTS_FILE = "native.txt";
	private static final String USER_INPUT_FILE = "user_input.txt";
	private static final String XSS_RETURN_FILE = "xss_return.txt";
	private static final String XSS_PARAM_FILE = "xss_param.txt";
	private static final String AUTH_FAIL_FILE = "auth_fail.txt";
	private static final String SECURE_CLASS_FILE = "secure_class.txt";
	private static final String AUDIT_METHOD_FILE = "audit_method.txt";
	private static final String TIMER_METHOD_FILE = "timer_method.txt";
	
	public static void runPerformanceTest() {
		long lc = loadClasses();
		long cu = createUsers(500);
		long no = sendNativeObjects(500);
		long ui = runUserInput(500);
		long xr = runXssReturn(500);
		long xp = runXssParam(500);
		long af = runAuthFail(500);
		long sc = runSecureClass(500);
		long am = runAuditMethod(500);
		long tm = runTimerMethod(50);
		
		appendToFile(LOAD_CLASSES_FILE, lc);
		appendToFile(CREATE_USERS_FILE, cu);
		appendToFile(NATIVE_OBJECTS_FILE, no);
		appendToFile(USER_INPUT_FILE, ui);
		appendToFile(XSS_RETURN_FILE, xr);
		appendToFile(XSS_PARAM_FILE, xp);
		appendToFile(AUTH_FAIL_FILE, af);
		appendToFile(SECURE_CLASS_FILE, sc);
		appendToFile(AUDIT_METHOD_FILE, am);
		appendToFile(TIMER_METHOD_FILE, tm);
		
		System.out.println("Time to load classes: " + lc + " ms");
		System.out.println("Time to create Users: " + cu + " ms");
		System.out.println("Time to send objects: " + no + " ms");
		System.out.println("Time to run user input test " + ui + " ms");
		System.out.println("Time to filter XSS return " + xr + " ms");
		System.out.println("Time to filter XSS param " + xp + " ms");
		System.out.println("Time to fail auth " + af + " ms");
		System.out.println("Time to secure class " + sc + " ms");
		System.out.println("Time to audit method " + am + " ms");
		System.out.println("Time to run timer " + tm + " ms");
	}
	private static long loadClasses() {
		System.out.println("Loading classes...");
		long start = System.currentTimeMillis();
		
		@SuppressWarnings("unused")
		User user = UserRegistry.addUser("temp", "temp");
		
		@SuppressWarnings("unused")
		NativeObject no = new NativeObject();
		FilterNetworkTest.sendObj(new Object());
		
		UserInputTest.doTest();
		
		LoginStatusFilterTest.doTest();
		
		SecureClassTest.doTest();
		
		FilterMethodTest.filterMe("foo");
		
		TimerTest.doPerfTest();
		
		long end = System.currentTimeMillis();
		System.out.println("...finished loading classes");
		return end - start;
	}
	private static long createUsers(int n) {
		System.out.println("Starting createUsers...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			UserRegistry.addUser("user"+i, "password"+i);
		}
		long end = System.currentTimeMillis();
		System.out.println("...ending createUsers");
		return end - start;
	}
	private static long sendNativeObjects(int n) {
		System.out.println("Sending objects...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			try {
				FilterNetworkTest.sendObj(new NativeObject());
			}
			catch (Exception ex) {
				//Okay
			}
		}
		long end = System.currentTimeMillis();
		System.out.println("...finished sending");
		return end - start;
	}
	private static long runUserInput(int n) {
		System.out.println("Simulating user input...");
		long start = System.currentTimeMillis();		
		for (int i = 0 ; i < n ; i++) {
			UserInputTest.doTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...finished simulation");
		return end - start;
	}
	private static long runXssReturn(int n) {
		System.out.println("Running XSS return...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			SanitizeHTMLTest.doTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping XSS return");
		return end - start;
	}
	private static long runXssParam(int n) {
		System.out.println("Running XSS param...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			XSSFilterTest.doTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping XSS param");
		return end - start;
	}
	private static long runAuthFail(int n) {
		System.out.println("Running auth fail...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			LoginStatusFilterTest.doTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping auth fail");
		return end - start;
	}
	private static long runSecureClass(int n) {
		System.out.println("Running secure class...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			SecureClassTest.doTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping secure class");
		return end - start;
	}
	private static long runAuditMethod(int n) {
		System.out.println("Running audit method...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			FilterMethodTest.filterMe("foo");
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping audit method");
		return end - start;
	}
	private static long runTimerMethod(int n) {
		System.out.println("Running timer method...");
		long start = System.currentTimeMillis();
		for (int i = 0 ; i < n ; i++) {
			TimerTest.doPerfTest();
		}
		long end = System.currentTimeMillis();
		System.out.println("...stopping timer method");
		return end - start;
	}
		
	/****** Util functions ******/
	
	private static void appendToFile(String fileName, long l) {
		try {
			File file = new File(OUTPUT_DIRECTORY+"/"+fileName);
			if (!file.exists()) {
				file.createNewFile();
			}
			FileWriter writer = new FileWriter(file, true);
			
			writer.append(l+" ");
			writer.flush();
			writer.close();
		} catch (IOException e) {
			System.out.println("Could not append to file " + fileName);
			return;
		}
	}
}
